# -*- coding: utf-8 -*-

# File Name： register_factory
# Description :
# Author : lirui
# create_date： 2022/6/3
# Change Activity:
import copy

from .register import Registry
from ...misc.log_util import logger


class RegisterFactory:
    def __init__(self):
        self.register_mapping = {}

    def create_registry(self, registry_name) -> Registry:
        """
        Create a new registry.

        Args:
            registry_name: name of registry, if must be unique.

        Returns:
            Registry

        """
        if self.contain(registry_name):
            raise Exception(f'{registry_name} is already added in RegisterFactory.')
        self.register_mapping[registry_name] = Registry(registry_name)
        logger.debug(f'Create a new Registry {registry_name} from RegisterFactory.')
        return self.register_mapping[registry_name]

    def contain(self, key):
        """
        check whether the key in register_mapping

        Args:
            key:

        Returns:

        """
        return key in self.register_mapping

    def get_register(self, key):
        """
        get register from key

        Args:
            key:

        Returns:

        """
        return self.register_mapping[key]

    def get_callable(self, register_name, callable_name):
        """

        Args:
            register_name:
            callable_name:

        Returns:

        """
        register = self.register_mapping[register_name]
        return register.get(callable_name)

    def remove(self, key):
        """

        Args:
            key:

        Returns:

        """
        if key in self.register_mapping:
            del self.register_mapping[key]

    def refresh_config(self, key):
        """
        refresh_config

        Args:
            key:

        Returns:

        """
        self.register_mapping[key] = Registry(key)

    def build(self, registry_name, callable_name, cfg):
        """
        Build an object or execute callable function

        Args:
            registry_name:
            callable_name:
            cfg:

        Returns:

        """
        if not self.contain(registry_name):
            raise Exception(f'{registry_name} not in RegisterFactory.')
        registry = self.register_mapping[registry_name]
        return registry.build(callable_name, cfg)

    def build_from_config(self, registry_name, cfg, callable_name=None):
        """
        Build object from config.

        Args:
            callable_name: equal to 'type' in callable.
            registry_name:
            cfg:  including type.

        Returns:

        """
        tmp_cfg = copy.deepcopy(cfg)
        if callable_name is None:
            callable_name = tmp_cfg.pop('type')
        assert 'type' not in tmp_cfg, 'type is Reserved fields for callable name.'
        return self.build(registry_name, callable_name, tmp_cfg)


REGISTER_FACTORY = RegisterFactory()
